<!DOCTYPE html>
<html>
	<head>
		<title>GA JS Test</title>
		<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />

		<script type="text/javascript" src="js/jquery-1.11.1.min.js"></script>
		<script type="text/javascript" src="js/json2.js"></script>
		<script type="text/javascript" src="js/format4js.js"></script>
		<script type="text/javascript" src="js/plotly-latest.min.js"></script>

		<script type="text/javascript" src="js/ga.js"></script>
		<script type="text/javascript" src="js/nn.js"></script>

		<style type="text/css">
			.result {
				padding: 5px 10px;
			}

			.result>.chart {
				border: 1px solid black;
				padding: 5px 10px;
				margin-bottom: 10px;
				margin-right: 10px;
				width: 320px;
				height: 240px;
				float: left;
			}

			.clear {
				clear: both;
			}
		</style>
	</head>
	<body>
		<button type="button" onclick="testGA()">TEST GA</button>
		<button type="button" onclick="testGATrainNN()">TEST GA TRAIN NN</button>
		<span class="short"></span>
		<div class="result"></div>
		<script type="text/javascript" comment="common">
			function beginShow() {
				var container = $('.result');
				container.empty();
			}

			function endShow() {
				var container = $('.result');
				container.append('<div class="clear"></div>');
			}

			function showFigure(title, series, options) {
				var container = $('.result');

				let div = $('<div>');
				div.attr('tagFile', title);
				div.addClass('chart');

				container.append(div);

				Plotly.plot(div[0], series, options);
			}
		</script>
		<script type="text/javascript" comment="testGA">
			function testGA() {
				$.esmool.gaInit(beginShow, showDogs, endShow);

				let xmin = -1, xmax = 2, dx = xmax - xmin, killingRate = 0.3;
				let target = x => x * Math.sin(3 * Math.PI * x);
				let goodness = x => -1 * target(x);
				let babyMaker = (x, y) => (x + y) / 2;
				let mutator = x => {
					let t = x + (2 * Math.random() - 1) * dx * 0.001;
					return t > xmin && t < xmax ? t : x;
				};
				let successChecker = dogs => {
					let min = Infinity, max = -Infinity;
					for (let dog of dogs) {
						min = min >= dog ? dog : min;
						max = max <= dog ? dog : max;
					}
					return max - min < 1e-2;
				};

				let result = $.esmool.ga(100, 50, xmin, xmax, target, goodness, babyMaker, mutator, successChecker, killingRate);

				let short = $('.short');
				let logger = x => short.text(x);

				let success = result.success;
				let iterations = result.iterations;
				if (!success) {
					logger(String.format("No solution found, iterations %d exceed limit", iterations));
					return;
				}

				let dog = result.theOne;
				let fval = target(dog);
				logger(String.format("After %d iterations solution found at (%f, %f)", iterations, dog, fval));
			}

			function /* void */ showDogs(/* double[] */ dogs, /* Function<Double, Double> */ target, /* String */ dataTitle, /* double */ xmin, /* double */ xmax) {
				let title = String.format("---- %s ----", dataTitle);

				let xs = [], dx = (xmax - xmin) / 100;
				let data0 = { x: [], y: [], type: 'scatter', name: 'target', mode: 'lines' };
				for (let x = xmin; x<xmax+dx; x+=dx) {
					let y = target(x);
					data0.x.push(x);
					data0.y.push(y);
				}

				let data1 = { x: [], y: [], type: 'scatter', name: 'dogs', mode: 'markers', marker: { size: 5 } };
				for (let i = 0; i < dogs.length; i++) {
					let x = dogs[i];
					let y = target(x);
					data1.x.push(x);
					data1.y.push(y);
				}

				showFigure(title, [data0, data1], {
					title: title,
					showlegend: false,
					margin: { l: 20, r: 20, t: 30, b: 20 , pad: 0 },
					hovermode: false
				});
			}
		</script>
		<script type="text/javascript" comment="TEST GA TRAIN NN">
			function testGATrainNN() {
				var config = [
					{ count: 3, activateType: 'id' },
					{ count: 5, activateType: 'sigmoid' },
					{ count: 2, activateType: 'sigmoid' }
				];

				var settings0 = $.esmool.nnConfig(config);
				var settings1 = $.esmool.nnMutate(settings0, 1, x => x * (1 + 0.2 * (Math.random() * 2 - 1)));
				var network0 = $.esmool.nnBuild(settings0);
				var network1 = $.esmool.nnBuild(settings1);

				var input = new Array(3);
				for (var i=0; i<3; i++)
					input[i] = Math.floor(Math.random() * 10);

				var output0 = network0(input);
				var output1 = network1(input);
			}
		</script>
	</body>
</html>